﻿#include "study05.h"
// C/C++ 学习网站：https://legacy.cplusplus.com 注意旧版本（搜索）和新版本
class MyString {
private:
	char* m_buffer;
	size_t m_length; // 字符串字符个数，不包括结尾的空字符 '\0'
public:
	/*MyString(const MyString& str) // 默认的复制构造函数，只拷贝签名，所以是引用
		: m_buffer(str.m_buffer), m_length(str.m_length) {} */
		//MyString(const MyString& str) = delete; // 删除默认的复制构造函数，防止误用，str 可以不写

	MyString(const MyString& str)
		: m_length(str.m_length) // 只要不是指针或引用，都可以直接赋值，因为本身就是复制
	{ // 自定义的复制构造函数（重载），拷贝长度，并分配新的内存
		m_buffer = new char[m_length + 1];
		size_t i;
		for (i = 0; i < m_length + 1; ++i) // 循环拷贝字符
			m_buffer[i] = str.m_buffer[i];
		cout << "deep copied is success" << endl;
	}

	MyString(const char* str) {
		m_length = strlen(str);
		m_buffer = new char[m_length + 1];
		//strcpy(m_buffer, str); // 存在危险的字符串拷贝函数
		//memcpy(m_buffer, str, m_length + 1); // 安全的字符串拷贝函数
		size_t i;
		for (i = 0; i < m_length + 1; ++i) // 循环拷贝字符
			m_buffer[i] = str[i];
	}

	~MyString() {
		delete[] m_buffer; // 释放内存
	}

	char& operator[](size_t index) { // 重载下标引用运算符，引用类似指针
		return m_buffer[index];
	}
protected:
	friend std::ostream& operator<<(std::ostream& os, const MyString& str); // 友元函数声明
};

std::ostream& operator<<(std::ostream& os, const MyString& str) { // 友元函数，重载输出运算符
	os << str.m_buffer;
	return os;
}

static void print_MyString(const MyString& str) { // 这里使用引用防止多次复制构造函数的调用
	cout << "MyString: " << str << endl;
}

void test_copy_fuc() {
	print_start("复制构造函数测试");
	const char* str1 = "my name is shake_m";
	MyString str2(str1);
	MyString str3 = str2; // 这里是浅拷贝（只拷贝了指针），此时 str2 和 str3 都指向同一块堆区内存
	str2[3] = 'N'; // 修改 str2 内容
	cout << "str1: " << str1 << endl;
	print_MyString(str2);// 定义了析构函数，会自动释放一次内存
	print_MyString(str3);// 不定义自己的拷贝构造函数时会报错，定义了析构函数，释放内存一次后不能再次释放
	print_end("复制构造函数测试");
}